home *** CD-ROM | disk | FTP | other *** search
- /*
- File: History.c
-
- Description:
- These routines are used to store visitled links.
-
- HTMLSample is an application illustrating how to use the new
- HTMLRenderingLib services found in Mac OS 9. HTMLRenderingLib
- is Apple's light-weight HTML rendering engine capable of
- displaying HTML files.
-
- Copyright:
- © Copyright 1999 Apple Computer, Inc. All rights reserved.
-
- Disclaimer:
- IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Change History (most recent first):
- Wed, Dec 22, 1999 -- created
- */
-
-
- #include "History.h"
- #include <stddef.h>
- #include <Memory.h>
- #include <TextUtils.h>
- #include <Errors.h>
- #include <string.h>
-
-
-
- /* individual elements in the history are stored in a linked
- list. it's a two way list for easy insertions and deletions. */
- typedef struct HistoryStruct HistoryRecord;
- typedef HistoryRecord *HistoryPtr, **HistoryHandle;
- struct HistoryStruct {
- HistoryHandle prev, next;
- char url[1];
- unsigned char printName[1];
- };
-
- /* the history data handle contains a list of history
- elements along with a pointer to the current
- element being displayed. */
- struct HistoryData {
- HistoryHandle first, last;
- HistoryHandle current;
- };
-
-
-
- /* NewHistory creats a new history and returns
- a handle to it. Here, we just return an handled
- set to zero. */
- HistoryDataHandle NewHistory(void) {
- return (HistoryDataHandle) NewHandleClear(sizeof(HistoryData));
- }
-
-
- /* DisposeHistory disposes of a history and all of the
- structures allocated for it. */
- void DisposeHistory(HistoryDataHandle hd) {
- HistoryHandle rover, temp;
- rover = (**hd).first;
- /* delete all of the elements in the history list */
- while (rover != NULL) {
- temp = rover;
- rover = (**rover).next;
- DisposeHandle((Handle) temp);
- }
- DisposeHandle((Handle) hd);
- }
-
-
- /* AddToHistory adds a new element to the history. Both
- the URL and the printed representation of its url
- are stored. NOTE: if we have called GoBack a few times
- before this call, then those previously viewed items
- are removed from the history. This is so if we choose
- GoBack again, then we will arrive at the same link we
- are looking at now. */
- OSErr AddToHistory(HistoryDataHandle hd, char const* url, StringPtr printName) {
- HistoryHandle hrec, rover;
- long strbytes;
- /* create a new history record */
- strbytes = strlen(url);
- hrec = (HistoryHandle) NewHandle(offsetof(HistoryRecord, url) + strbytes + 1 + printName[0] + 1);
- if (hrec == NULL) return memFullErr;
- BlockMoveData(url, (**hrec).url, strbytes + 1);
- BlockMoveData(printName, (**hrec).url + strbytes + 1, printName[0] + 1);
- (**hrec).prev = (**hrec).next = NULL;
- /* clear out records after current. We do this
- so the next time we choose the go back command,
- we'll arrive at the same one that was the current
- one before this routine was called. Essentially, the
- user is conducting a depth first search of the html,
- and here we are branching. */
- while ((**hd).current != (**hd).last && (**hd).current != NULL) {
- rover = (**(**hd).current).next;
- if ((**rover).next != NULL)
- (**(**rover).next).prev = (**rover).prev;
- else (**hd).last = (**rover).prev;
- if ((**rover).prev != NULL)
- (**(**rover).prev).next = (**rover).next;
- else (**hd).first = (**rover).next;
- DisposeHandle((Handle) rover);
- }
- /* add the new record to the end of the list */
- if ((**hd).first == NULL)
- (**hd).first = (**hd).last = hrec;
- else {
- (**hrec).prev = (**hd).last;
- (**(**hd).last).next = hrec;
- (**hd).last = hrec;
- }
- (**hd).current = hrec;
- return noErr;
- }
-
-
- /* InHistory returns true if the URL is among the urls
- currently stored in the history. */
- Boolean InHistory(HistoryDataHandle hd, char const* url) {
- HistoryHandle rover;
- Boolean isequal;
- for (rover = (**hd).first; rover != NULL; rover = (**rover).next) {
- HLock((Handle) rover);
- isequal = (strcmp(url, (**rover).url) == 0);
- HUnlock((Handle) rover);
- if (isequal) return true;
- }
- return false;
- }
-
-
- /* CanGoBack returns true if it makes sense to call the
- GoBack command. i.e. if there are one or more links
- in the history beyond the current one. */
- Boolean CanGoBack(HistoryDataHandle hd) {
- if ((**hd).current == NULL)
- return false;
- else return ((**(**hd).current).prev != NULL);
- }
-
-
- /* GoBack copies the previous url in the history
- into a new handle and returns that handle in
- *url. It is the caller's responsibility to dispose
- of the handle after it has been used. */
- OSErr GoBack(HistoryDataHandle hd, Handle *url) {
- OSErr err;
- HistoryHandle nextcurrent;
- if ((**hd).current == NULL) return paramErr;
- nextcurrent = (**(**hd).current).prev;
- HLock((Handle) nextcurrent);
- err = PtrToHand((**nextcurrent).url, url, strlen((**nextcurrent).url) + 1);
- HUnlock((Handle) nextcurrent);
- if (err == noErr)
- (**hd).current = nextcurrent;
- return err;
- }
-
-
- /* CanGoForward returns true if it makes sense to call the
- GoForward command. i.e. if there are one or more links
- in the history ahead of the current one. This can only
- happen after the user has chosen GoBack one or more
- times. */
- Boolean CanGoForward(HistoryDataHandle hd) {
- if ((**hd).current == NULL)
- return false;
- else return ((**(**hd).current).next != NULL);
- }
-
-
- /* GoForward copies the next url in the history
- into a new handle and returns that handle in
- *url. It is the caller's responsibility to dispose
- of the handle after it has been used. */
- OSErr GoForward(HistoryDataHandle hd, Handle *url) {
- OSErr err;
- HistoryHandle nextcurrent;
- if ((**hd).current == NULL) return paramErr;
- nextcurrent = (**(**hd).current).next;
- HLock((Handle) nextcurrent);
- err = PtrToHand((**nextcurrent).url, url, strlen((**nextcurrent).url) + 1);
- HUnlock((Handle) nextcurrent);
- if (err == noErr)
- (**hd).current = nextcurrent;
- return err;
- }
-
-
- /* CanGoHome returns true if it makes sense to call the
- GoHome command. i.e. if there are one or more links
- in the history. This can only happen after AddToHistory
- has been called one or more times. */
- Boolean CanGoHome(HistoryDataHandle hd) {
- return ((**hd).first != (**hd).current) && ((**hd).current != NULL);
- }
-
-
- /* GoBack copies the first url in the history
- into a new handle and returns that handle in
- *url. It is the caller's responsibility to dispose
- of the handle after it has been used. */
- OSErr GoHome(HistoryDataHandle hd, Handle *url) {
- OSErr err;
- if ((**hd).first == NULL) return paramErr;
- HLock((Handle) (**hd).first);
- err = PtrToHand((**(**hd).first).url, url, strlen((**(**hd).first).url) + 1);
- HUnlock((Handle) (**hd).first);
- if (err == noErr)
- (**hd).current = (**hd).first;
- return err;
- }
-
-
- /* AppendHistoryToMenu rebuilds the Go menu adding items to the
- bottom of the menu according to the items in the
- history. The names of the items are the same as
- the printNames provided in the AddToHistory command. */
- OSErr AppendHistoryToMenu(HistoryDataHandle hd, MenuHandle theMenu) {
- HistoryHandle rover;
- Str255 title;
- unsigned char *titlep;
- if ((**hd).last == NULL) return noErr;
- AppendMenu(theMenu, "\p(-");
- for (rover = (**hd).last; rover != NULL; rover = (**rover).prev) {
- HUnlock((Handle) rover);
- titlep = (unsigned char *) ((**rover).url + strlen((**rover).url) + 1);
- BlockMoveData(titlep, title, titlep[0] + 1);
- AppendMenu(theMenu, title);
- HUnlock((Handle) rover);
- }
- return noErr;
- }
-
-
- /* GoToMenuItem copies the itemIndex'th url in the history
- into a new handle and returns that handle in
- *url. It is the caller's responsibility to dispose
- of the handle after it has been used. This routine
- should only be called after a menu selection has
- been made in a menu built by AppendHistoryToMenu. */
- OSErr GoToMenuItem(HistoryDataHandle hd, Handle *url, short itemIndex) {
- HistoryHandle rover;
- short i;
- OSErr err;
- if ((**hd).last == NULL) return paramErr;
- for (i = 1, rover = (**hd).last; rover != NULL; rover = (**rover).prev, i++) {
- if (i == itemIndex) {
- HLock((Handle) rover);
- err = PtrToHand((**rover).url, url, strlen((**rover).url) + 1);
- HUnlock((Handle) rover);
- if (err == noErr)
- (**hd).current = rover;
- return err;
- }
- }
- return noErr;
- }